#include "Scenariu.h"

Scenariu::Scenariu(void)
{
	this->M = new Meniu();
	subheight = 5.0f;
	projection = 1;
	use_custom = false;
	custom_orto = false;
	use_fog = false;
	selected = -1;
};

void Scenariu::InitMenu(Meniu *Men)
{
	this->M = Men;
};

void Scenariu::init(void){
};

void Scenariu::Draw2D(void)
{
	this->M->Menudraw();
};

void Scenariu::Draw3D(void)
{
};

void Scenariu::mainDisplay (void) 
{
	glutSetWindow(winIdMain); 
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
	glLoadIdentity (); 
	glColor3f(1.0,1.0,1.0);
	glDisable(GL_DEPTH_TEST);

	glDisable(GL_LIGHTING);
	glEnable (GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	if (use_fog){
		glEnable(GL_FOG);
		glFogfv(GL_FOG_COLOR, ceata.culoare);
		if (ceata.type == LINIAR){
			glFogi(GL_FOG_MODE, GL_LINEAR);
			glFogf(GL_FOG_START, ceata.nearl);
			glFogf(GL_FOG_END, ceata.farl);
		}
		if (ceata.type == EXP){
			glFogi(GL_FOG_MODE, GL_EXP);
			glFogf(GL_FOG_DENSITY,ceata.dens);
		}
		if (ceata.type == EXP2){
			glFogi(GL_FOG_MODE, GL_EXP2);
			glFogf(GL_FOG_DENSITY,ceata.dens);
		}
	}
	//else 
		//glDisable(GL_FOG);
	glLineWidth(2.0);
	vector<Text>::iterator it;
	for ( it=this->texte.begin() ; it < this->texte.end(); it++ )
	{
		if (it->type == 2 && it->Visible){
			glColor3f (it->culoare[0], it->culoare[1], it->culoare[2]); 
			glRasterPos2f (it->x, it->y); 
			drawStringBig (it->str);
		}
		if (it->type == 3 && it->Visible)
		{
			glColor3f (it->culoare[0], it->culoare[1], it->culoare[2]); 
			glRasterPos2f (it->x, it->y); 
			drawStringSmall (it->str);
		}
	}
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_NORMALIZE);
	if (projection == 1)
		glEnable(GL_LIGHTING);

	// stim vectorul UpVector, folosim LookAt
	if (projection == 1){
		if (use_custom == true)
			custom_cam->Render();
		else
			c->Render();
		vector<Light *>::iterator itl;
		for ( itl=this->lights.begin() ; itl < this->lights.end(); itl++ )
			(*itl)->Render();
		vector<Plan *>::iterator it3;
		for ( it3=this->plans.begin() ; it3 < this->plans.end(); it3++ )
			(*it3)->draw();
		vector<Obiect3D *>::iterator it;
		for ( it=this->objects3D.begin() ; it < this->objects3D.end(); it++ )
			(*it)->draw();
	}
	vector<Obiect2D *>::iterator it2;
	for ( it2=this->objects2D.begin() ; it2 < this->objects2D.end(); it2++ )
		(*it2)->draw();
	if (projection == 1){
		vector<Light *>::iterator itl;
		for ( itl=this->lights.begin() ; itl < this->lights.end(); itl++ )
		{
			(*itl)->Draw();
			(*itl)->Disable();
		}
		for ( itl=this->lights.begin() ; itl < this->lights.end(); itl++ )
		{
			;	
		}
	}
	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();
};

void Scenariu::subDisplay () 
{ 
	glutSetWindow (winIdSub);
	glClearColor (0.25, 0.25, 0.25, 0.0);
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	this->M->Menudraw();
	vector<Text>::iterator it;
	for ( it=this->texte.begin() ; it < this->texte.end(); it++ )
	{
		if (it->type == 0 && it->Visible){
			glColor3f (it->culoare[0], it->culoare[1], it->culoare[2]); 
			glRasterPos2f (it->x, it->y); 
			drawStringBig (it->str);
		}
		if (it->type == 1 && it->Visible)
		{
			glColor3f (it->culoare[0], it->culoare[1], it->culoare[2]); 
			glRasterPos2f (it->x, it->y); 
			drawStringSmall (it->str);
		}
		if (it->type == 4 && it->Visible)
		{
			glColor3f (it->culoare[0], it->culoare[1], it->culoare[2]); 
			glRasterPos2f (it->x, it->y); 
			drawStringMedium (it->str);
		}
	}
	glutSwapBuffers (); 
};

void Scenariu::mainReshape (int w, int h) 
{ 
	if (projection == 1)
	{
		glViewport(0,0, (GLsizei) w, (GLsizei) h);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();

		//gluPerspective(proj_args[0],(float)w/h,proj_args[2],proj_args[3]);//45, (float)w/h, 1.0, 60.0);
		if (custom_orto == false){
			if (use_custom == true)
				glFrustum(proj_args[0], proj_args[1], proj_args[2], proj_args[3],proj_args[4],proj_args[5]);
			else {
				const double DEG2RAD = 3.14159265 / 180;
				double tangent = tan(45/2 * DEG2RAD);   // tangent of half fovY
				double height = 1 * tangent;          // half height of near plane
				double width = height * (float)w/h;
				proj_args[0] = -width;
				proj_args[1] = width;
				proj_args[2] = -height;
				proj_args[3] = height;
				proj_args[4] = 1;
				proj_args[5] = 60;
				glFrustum(proj_args[0], proj_args[1], proj_args[2], proj_args[3],proj_args[4],proj_args[5]);
			}
		}
		else
			glOrtho(proj_args[0], proj_args[1], proj_args[2], proj_args[3],proj_args[4],proj_args[5]);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity(); 
		// pregatim o scena noua in opengl
		glClearColor(0.0, 0.0, 0.0, 0.0);	// stergem tot
		glEnable(GL_DEPTH_TEST);			// activam verificarea distantei fata de camera (a adancimii)
		glShadeModel(GL_SMOOTH);			// mod de desenare SMOOTH
		glEnable(GL_LIGHTING);				// activam iluminarea
		glEnable(GL_NORMALIZE);
		glEnable(GL_COLOR_MATERIAL);

	}
	else {
		glClearColor(0.0, 0.0, 0.0, 0.0);	// stergem tot
		glDisable(GL_DEPTH_TEST);			// activam verificarea distantei fata de camera (a adancimii)
		glShadeModel(GL_SMOOTH);			// mod de desenare SMOOTH
		glDisable(GL_LIGHTING);				// activam iluminarea
		glDisable(GL_NORMALIZE);
		glViewport(0,0, (GLsizei) h, (GLsizei) h);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(proj_args[0],proj_args[1],proj_args[2],proj_args[3],-1.0f,1.0f);//-1.0F, 1.0F, -1.0F, 1.0F 
		glMatrixMode(GL_MODELVIEW);
		//glDisable(GL_DEPTH_TEST);
		glLoadIdentity(); 
	}
	// activam normalizarea normalelor
	glutSetWindow (winIdSub); 
	glutReshapeWindow (w - 10, h / subheight); 
	glutPositionWindow (5, 5); 
	glutSetWindow (winIdMain);
}; 

void Scenariu::subReshape (int w, int h) 
{ 
	glViewport (0, 0, w, h); 
	glMatrixMode (GL_PROJECTION); 
	glLoadIdentity (); 
	gluOrtho2D (0.0F, 1.0F, 0.0F, 1.0F);
}; 

void Scenariu::TransformToWorldCoords(GLdouble x , GLdouble y , GLdouble *newx,GLdouble *newy)
{
	GLint viewport[4]; 
	GLdouble modelview[16]; 
	GLdouble projection[16]; 
	GLdouble winX, winY, winZ; 
	GLdouble worldZ; 
	glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); 
	glGetDoublev( GL_PROJECTION_MATRIX, projection ); 
	glGetIntegerv( GL_VIEWPORT, viewport ); 
	winX = (GLdouble)x;
	winY = (GLdouble)viewport[3] - (GLdouble)y;
	winZ = 0;
	gluUnProject( winX, winY, winZ, modelview, projection, viewport, newx, newy, &worldZ);
};

void Scenariu::keyboard (unsigned char key, int x, int y) 
{
	switch (key){
	case ' ':
		printf("\n%d %d\n",selected,objects3D.size());
		if (selected != -1)
			objects3D[selected]->deselect();

		selected = (selected+1) % objects3D.size();
		while (objects3D[selected]->selectable == false )
			selected = (selected+1) % objects3D.size();
		objects3D[selected]->select();
	};
};


void Scenariu::mainMenu(int value)
{
};


void Scenariu::subMenu(int value)
{
};

void Scenariu::MouseButton(int button,int state,int x, int y)
{
	GLdouble newx,newy;
	TransformToWorldCoords((GLdouble) x, (GLdouble)y,&newx,&newy);
	MySoarec.x_mouse= newx;
	MySoarec.y_mouse = newy;
	printf("%f %f \n",newx,newy);
	if (state == GLUT_DOWN) 
	{
		if ( !(MySoarec.left_pressed || MySoarec.middle_pressed || MySoarec.right_pressed) ) {
			MySoarec.xp_mouse = newx;
			MySoarec.yp_mouse = newy;
		}

		switch(button) 
		{
		case GLUT_LEFT_BUTTON:
			MySoarec.left_pressed = true;
			M->Menupress(newx,newy);
			break;
		case GLUT_RIGHT_BUTTON:
			MySoarec.right_pressed = true;
			break;
		case GLUT_MIDDLE_BUTTON:
			MySoarec.middle_pressed = true;
			break;
		}
	}
	else 
	{
		switch(button) 
		{
		case GLUT_LEFT_BUTTON:
			MySoarec.left_pressed = false;
			button_changed = false;
			M->Menurelease(newx,newy,MySoarec.xp_mouse,MySoarec.yp_mouse);
			if (button_changed){
				process_button_and_make_changes();
				printf("%s\n",lastbutton);}
			break;
		case GLUT_RIGHT_BUTTON:
			MySoarec.right_pressed = false;
			break;
		case GLUT_MIDDLE_BUTTON:
			MySoarec.middle_pressed = false;
			break;
		}
	}
	glutPostRedisplay();
};


void Scenariu::MouseMotion(int x, int y)
{
	GLdouble newx,newy;
	TransformToWorldCoords((GLdouble) x, (GLdouble)y,&newx,&newy);
	MySoarec.x_mouse = newx;
	MySoarec.y_mouse = newy;
	M->Menupasiv(newx,newy,MySoarec.xp_mouse,MySoarec.yp_mouse);
	glutPostRedisplay();
};

void Scenariu::MousePassiveMotion(int x, int y)
{
	GLdouble newx,newy;
	TransformToWorldCoords((GLdouble) x, (GLdouble)y,&newx,&newy);
	MySoarec.x_mouse = newx;
	MySoarec.y_mouse = newy;
	M->Menupasiv(newx,newy,MySoarec.xp_mouse,MySoarec.yp_mouse);
};

void Scenariu::drawString (char *format,GLfloat x, GLfloat y) 
{ 
	va_list args;

	char buffer[1024],*p;

	va_start(args,format);

	vsprintf(buffer, format, args);

	va_end(args);

	glPushMatrix();

	glTranslatef(x,y,-15);

	//glRotatef(180,0,1,0);

	glScalef(0.0020, 0.0020, 0.0); /* 0.1 to 0.001 as required */

	for (p = buffer; *p; p++)
		glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);

	glPopMatrix();
};

void Scenariu::drawStringBig (char *s) 
{ 
	unsigned int i; 
	for (i = 0; i < strlen (s); i++) 
		glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24, s[i]); 
};
void Scenariu::drawStringSmall (char *s) 
{ 
	unsigned int i; 
	for (i = 0; i < strlen (s); i++) 
		glutBitmapCharacter (GLUT_BITMAP_HELVETICA_10, s[i]); 
};
void Scenariu::drawStringMedium (char *s) 
{ 
	unsigned int i; 
	for (i = 0; i < strlen (s); i++) 
		glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, s[i]); 
};
void Scenariu::SetSubHeight(float dim)
{
	subheight = dim;
};
Scenariu::~Scenariu(void)
{
};